//
//  ReadMe.h
//  HMWeiBo
//
//  Created by Apple on 16/7/28.
//  Copyright © 2016年 itheima. All rights reserved.
//

/*
 
 http://github.ibireme.com/github/list/ios/
 http://www.devdiv.com
 
 快捷键: 1. command + ~ 相同的工程直接来回切换
 
 面试题:
    1.面向对象的三大特点:
    2.控制器的生命周期(控制器View的生命周期),注意ViewDidLoad和ViewWillAppear的执行顺序
    3.你在网络接口调试过程中,遇到什么问题?
    4. status code: 200 网络请求成功
        status code: 303
 Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/plain" UserInfo={com.alamofire.serialization.response.error.response=<NSHTTPURLResponse: 0x7f8c884887e0> { URL: https://api.weibo.com/oauth2/access_token } { status code: 200, headers {
 "Cache-Control" = "no-cache";
 "Content-Length" = 117;
 "Content-Type" = "text/plain;charset=UTF-8";
 Date = "Fri, 29 Jul 2016 08:26:12 GMT";
 Expires = "Thu, 01 Jan 1970 00:00:00 GMT";
 Pragma = "No-cache";
 Server = "nginx/1.6.1";
 "api-server-ip" = "10.75.2.82";
 } }, NSErrorFailingURLKey=https://api.weibo.com/oauth2/access_token, com.alamofire.serialization.response.error.data=<7b226163 63657373 5f746f6b 656e223a 22322e30 30544232 5633477a 39774a58 42626237 34333563 3037326f 42437748 43222c22 72656d69 6e645f69 6e223a22 31353736 37393939 39222c22 65787069 7265735f 696e223a 31353736 37393939 392c2275 6964223a 22353832 39333435 33363722 7d>, NSLocalizedDescription=Request failed: unacceptable content-type: text/plain}
 
    5.沙盒路径的文件夹有几个?
        Document: 由于保存用户的重要信息;举例就是数据库
        Library:
                Cache: 用于存在SDWebIamge的缓存
                Preferences: 保存用户的偏好设置
        Temp: 临时文件夹
 
    6.约束动画如何实现?
         // 约束动画需要view调用一下 layoutIfNeeded
         self.view.layoutIfNeeded()
 
    7.闭包.代理  和 通知的 区别
        1. 通知是 多对一; 代理和闭包是 一对一
        2. 通知可以跨多个层进行传值; 代理和闭包不可以
 
    8. layoutsubViews 在什么时候调用
        1. frame发生改变的时候,会调用
        2. 添加子控件的时候回调用
        3. UIScrollView 滑动的时候会调用
    9.  先下载3个,再下载4个,最后再下载4个,都下载完成之后告诉我
        dispath_group
 
    10.UIButton的父类->UIControl
        平时开发有没有自定义UIControl
 
    11.UIView和CALayer的区别
        1. 父类来出来 UIView的父类是 UIResponser;CALayer 的父类是 NSOject
        2. UIView 在UIKit框架里; CALayer是 QuartCore
        3. UIView里 有CALayer
 
 
 经常用到的编程思想
    1.分析普通的实现,再去分析特殊的实现(效果/功能);
    2.先去实现我们肉眼所看到的界面;再去实现功能
    3.任何问题都有2种解决思路: 第一种: 最原始的,最笨的方式;第二种:在第一种的基础上做优化
    4.针对一下效果/或者功能/宽高等数值/UIView,我们探索思路的时候,可以随便写一个,或者随便定义一个黑盒方法来达到这样的效果
    5. 我们需要找一些关键点.或者说时间点.或者说 事件点
    6. 针对效果或者bug驱动,来实现下一步的代码
    7. 针对于现象提出改善的方案,再用另外一个方法解决这个问题
 
 一 自定义Tabbar的实现
    1. 先去实现4个普通的item,最后再去分析那个特殊的功能
    2. 添加了4个子视图控制器
    3. 用现在的效果和最终的效果进行比对,然后再分析思路
    
    4. 添加一个按钮控件
    5. 想要添加按钮控件,需要给按钮控件位置! 修改控件的位置一般是在layoutsubviews.我们就考虑到 这4个控件的父视图是 UITabBar -> 自定义UITabbar,然后去实现它的 layoutsubviews
    6. KVC给私有属性赋值
 
 二.访客视图
 
    1. 访客视图的所有控制器都用同一个View
    2. 添加控件
    3.实现功能:首页转动动画;按钮的点击
    
 
 微博项目第二天
 
    三. oauth认证
        1.我们的app去显示那个web页面
        2.我们需要获取到这个含有code的url,去截取code
        3.拿code去发送一个网络请求,去换取token
 
    四. 注册成为weibo的开发者
        0.微博账号
        1.打开open.weibo.com
        2.打开 我的应用,去完善个人基本信息. 注意: 身份认证和支付信息不用做
        3.完善个人信息,除了邮箱是正确(邮箱需要验证),其他的都可以随便写
        4.2分钟之后,登录验证邮箱进行激活
    五.在开发者账号中,创建一个APP所对应的信息 -- 这些信息会与微博服务器校验
 
        1.点击微连接的 移动应用
        2.点击创建
        3.完善信息之后,点击创建
        4.在基本信息界面,什么都不用填写;保存appkey和appscrect信息
        5.在高级信息里,设置请求回调页面; 保存 请求回调页 http://www.itheima.cn
        6.设置测试信息
    六.接口文档的学习
 
        1.请求的url
        2.请求方式:如果要求是POST,你偏偏采用了get会导致失败
        3.请求参数: 特别注意是否是 必选.如果是必选是,这个key必须有对应的值放在网络请求里;如果是非必须,我们进行接口调试的时候,可以忽略
            https://api.weibo.com/oauth2/authorize?client_id=1406121621&redirect_uri=http://www.itheima.cn&language=en
        4.返回数据
            用哪个,找哪个,不用特意看所有的
        5.示例(有可能有,有可能没有).
 
 
    七.欢迎界面
        1.界面的搭建
        2.动画的实现--约束动画; 视图的生命周期
 
 
    八.界面跳转的逻辑 -- 就相当于产品经理设置的页面跳转逻辑,会在圆形里有很好的展示
        1.当我们没有登录的时候,进入的是 访客视图界面
        2.当我们登录了的时候,进入的是欢迎界面;欢迎界面之后是首页
        3.当我们点击注册的时候,会跳转到oauth,oauth授权成功之后,会跳转到欢迎界面
    
    九.OC/swift里的通知
        1.发送一个通知;
        2.监听通知;
        3.移除通知;
        4.实现通知的监听方法
 
 
 项目第4天
   十. 归档和接档 -- NSUserDeault
    归档和接档是 保存的对象; 能够归档成为一个文件;
        1.实现NSCoding协议
        2.归档和接档的时机 -- 对象有值了就保存;
    NSUserDeault保存的是 NSArray和NSDictinanary;把对象的属性的值拿出来,一个一个的保存;小数据(用户的 是否保存密码; 是否接受音乐;)
 
    首页视图分析
     十一.
        1.原创微博
            没有配图的微博
            有配图的微博
            1,2,3,4,5,6,7,8,9
        2.转发微博
            转发微博没有配图
            转发微博有配图
            1,2,3,4,5,6,7,8,9
 
        一]原创微博的视图 分2部分
            1. 原创微博View
                头像
                名字
                时间/来源
                内容
            2.底部功能视图
                转发评论和点赞
        二]转发微博的视图 分3部分
            1.原创微博View
            2.转发微博View
                原创的内容
            3.底部功能视图
         三 ]原创微博有配图的视图 分2部分
         1. 原创微博View
         头像
         名字
         时间/来源
         内容
            配图 !!!!!!!!!!!
         2.底部功能视图
            转发评论和点赞
 
         四]转发微博有配图的视图 分3部分
         1.原创微博View
         2.转发微博View
         原创的内容
            配图!!!!!!!!!!!!
         3.底部功能视图
 
    十二.转发微博的约束该怎么加?
        1.可以认为所有的微博都是转发微博
        2.原创微博的时候,也显示了 转发微博. 应该让 原创微博的时候,隐藏/转发微博的高度为0
 
    十三.配图实现的思路
 
        1. 我们采用最笨的思路.来分析
            1张图片: 显示的是 图片的实际大小
            2张图片: 2张图片大小一样; 有间隔;距离左边有一个距离
            3张图片: 配图距离Cell的左右2边都相等.剩余的是 图片的宽度和 2个间距
            4张图片: 2*2的
            5张图片: 发现规律: 九宫格: 宽度 = 3张图片的宽度;高度 = 行数 * (cell的高度 + 间隔)
            6,7,8,9
        2. 按照 有普通到特殊的思想 把 1张图片和4张图片 放到最后实现
        3. 2 3 5 6 7 8 9 -> 什么控件才能显示  UICollectionView
            再去思考一下,特殊的可不可以实现
        4.  一 .调用数据源之前,需要把数据传递过去 -> didSet
            二 .计算好了 高和宽
            三 .调用UICollectioView的数据源之前,就得告诉我们 这个视图的宽和高
            我们如果去根据图片的数量去修改宽和高?
 
        把思路如何转换成代码?
        1. 自定义一个UICollectionView
        2. 添加到Cell -- 约束该怎么加? 随便加
        3. 数据源方法以及 UICollectionView的其他设置
        4. 数据传递, didSet里计算 宽和高
 
    十四.下拉刷新 -- 所有的思路都来源于系统的下拉刷新
        1. 由于我们的界面是全新的,没有必要继承自系统的下拉刷新,所以我们继承了 UIControl -> 自定义了UIControl
        2. 把这个自定义视图,添加到了 tableView里;没有设置大小,系统的下拉刷新设置了默认的宽和高,设置一个固定的宽和高;又设置了一下Y值
        3.添加子控件,然后设置约束
        4.我们去分析demo/产品经理的要求,来查找线索;contentOffset.y值发生改变,对应的效果才会改变
        5. KVO -> 监听 contentOffset 这个属性值的改变
        6. willMoveToSuperview 把监听方法移动到 HMRefreshView里
        7(重要!!!). 分析下拉刷新的三种状态--临界点
        8. 我们结合 contentOffset.y 与 scrollView.dragging 这2个线索,来分析临界值
 
        9. 记录这个状态值的改变.来分别实现对应的效果
        10. 优化 -- 用一个标记位来排除状态的多次改变
        11. 根据效果/遇到的bug 去解决问题
                1.加载中的时候,视图下沉一下
                2.加载中的时候,需要调用 UIControl的方法  sendActionsForControlEvents
                3. 去实现一下,加载完成之后,恢复视图的问题
                4. 视图下沉会在第一次加载数据的时候调用 -- bug
 
 
    十五.pop动画
        1. 点击 加号 按钮会出现一个视图
        2. 界面有6个按钮 -> 界面有 6个 自定义的按钮; 图片位置和文字标题位置需要我们重新布局
        3. 动画 -- pop动画-> facebook
        4. 背景 -- 截图微博的图片,然后添加毛玻璃效果
        5. 按钮点击 -- 被点击的按钮进行了放大处理.没有点击的按钮边小了.都消失了.最后modle出一个控制器
        6. 视图消失
 
    十六.图片选择器的思路
        1.UICollectionView
        2.UICollectionViewCell -> 1.展示选择的图片 2.关闭按钮/删除按钮
        3.当没有选择图片的时候/9张图片的时候,没有 加号按钮
            当有 1 ~ 8张的是时候,有加号按钮
            加号按钮能够跳转到图片选择的界面
 
        转化成步骤
        1. 自定义一个UIView继承自UICollectionView
        2. 添加到发布微博界面
        3. 设置数据源方法.设置属性
        4. 自定义Cell -> 视图三部曲
        5. Cell里添加删除按钮.然后实现删除功能
        6. 实现加号按钮的显示
        7. 实现加号按钮的功能
 
        条件反射/固定思维 -- 有利有弊
 

    十七.表情键盘
        1.视图是分2部分.上部分-- UIScrollView --
                                UICollectionView --
                        一.思路: 底部一个分类,对应 UICollectionView的一个 Section
 
                     二.思路: 如果一个Cell里会有 20 + 1个表情
                                这些表情,我们通过循环来添加到Cell里
 

                    下部分-- 4个button;4个按钮是平铺的;UIStackView
 
 
    十八.代码抽取的步骤 -- 代码的抽取原则: 原来的代理涉及到的对象很单一,而且代码量也很大
 
     1. 把要抽取的代码,复制到指定位置/指定方法
     2. 把需要的对象,以参数的形式体现
     3. 当抽取的代码没有问题的时候,把原来的代码删除
 
 
    十九.图片浏览器
    1. 点击图片model出一个视图
    2. 界面的分析 : 2个按钮.UICollectionView
    3. 设置UICollectionView的属性和数据源方法
    4. 自定义Cell
    5. 刚开始显示的小图
    6. 小图有一个加载的效果 -- 跳过去
    7.小图显示完成之后就是大图
 
 
 
 
1.项目整体采用MVVM架构,将试图与控制器进行管理,将网络请求/数据处理放置在ViewModel,充分解耦
2.项目所用到的一些设计模式,包括 单例设计模式/通知设计模式/代理设计模式/Targe-Action设计模式/工厂设计模式/桥接设计模式
3.整个项目抽取出HTTPClient网络工具类.在底层对数据请求成功与失败进行处理.每个控制器与HTTPClient进行关联,充分解耦
 4.项目开发过程中,抽取了 BaseViewController. BaseViewController中有加载数据的视图,共有的参数,共有的动画等
 5.数据是采用FMDB进行数据库存储
 6.下拉刷新是采用自定义实现,其中动画采用核心动画实现
 7.抽取了一个Common类,这个类有UIButton/UILable/UITextView等其他控件的扩展方法
 
 
 1. 生活圈采用了MVC框架进行设计.其中里边有涉及到单例设计模式/工厂设计模式/...
 2. 网络请求是继承自AFN,单独抽出了一个网络工具类.网络工具类是采用类方法调用;在网络请求里,对数据进行底层处理
 3. 整个项目封装了2个基类:BaseViewVC和NavBaseVC.把共有的一些功能进行封装;Common文件夹有对UIButton/UILabl等的一些封装,拿来就用
 4.首页的无限滚动采用 3个Cell实现无限复用
 5.一些核心动画~~~~
 6.首页功能以及支付页面是有我独立完成的
 
 
 // 自定义视图三部曲
 
 // 第一步: 重写父类的构造函数
 override init(frame: CGRect) {
 super.init(frame: frame)
 }
 
 required init?(coder aDecoder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
 
 // 第二步: 定义一个添加子类和设置子类控件约束的方法
 private func setupUI(){
 
 
 }
 
 //第三步: 懒加载控件
 //MARK:-- 懒加载控件
 
 */
